use std::cell::RefCell;
use std::rc::Rc;

use crate::get_val_from_vm_val_enum;
use crate::heap::vm_heap::VMHeap;
use crate::instruction::instruction::Instruction;
use crate::vm_thread::{VMFrame, VMThread};
use crate::vm_val::{VMValEnum, VMValInteger};

pub struct arraylength {}

impl Instruction for arraylength {
    fn exec(&mut self, frame: Rc<RefCell<VMFrame>>, thread: &VMThread) {
        let ro_frame = frame.borrow();
        let mut rw_operand_stack = ro_frame.operand_stack.borrow_mut();
        let arr_enum = rw_operand_stack.pop().unwrap();

        let arr_ref = get_val_from_vm_val_enum!(&arr_enum, VMValRef);
        let arr = VMHeap::get_vmobject(arr_ref.clone()).unwrap();
        assert!(arr.is_arr, "类型不匹配，此指令仅支持数组");
        rw_operand_stack.push(VMValEnum::VMValInteger { val: VMValInteger { num: arr.arr_len as i32 } })
    }

    fn to_string(&self) -> String {
        String::from("arraylength")
    }
}